package yinshi.j2d;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import yinshi.j2d.geom.Rectangle;

public class JCanvas extends javax.swing.JPanel {

    private final BranchGroup root = new BranchGroup();
    private final AffineTransform viewpoint = new AffineTransform();
    private Point p1;
    private Point p2 = new Point();

    public JCanvas() {
        this.setBackground(Color.WHITE);
        this.setDoubleBuffered(true);
        initCanvas();
    }

    private void initCanvas() {
        final TransformGroup group = new TransformGroup();

        Rectangle rect = new Rectangle(200, 100);
        rect.setStroke(new BasicStroke(2.0f));
        rect.setForeground(Color.BLACK);
        rect.setBackground(Color.GREEN);

        Shape2D shape = new Shape2D();
        Path2D path = new Path2D.Double();
        path.moveTo(0, 0);
        for (int i = 0; i < 100; i++) {
            double x = (Math.random() - 0.5) * 500;
            double y = (Math.random() - 0.5) * 500;
            path.lineTo(x, y);
        }
        shape.setForeground(Color.BLUE);
        shape.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        shape.setShape(path);
        group.add(shape);

        final AffineTransform transform = group.getTransform();

        Timer t = new Timer();
        t.schedule(new TimerTask() {
            public void run() {
                transform.rotate(Math.PI / 120);
                repaint();
            }
        }, 10000, 10);

        root.add(group);
    }

    public BranchGroup getRoot() {
        return root;
    }

    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D g2d = (Graphics2D) g;
        AffineTransform transform = g2d.getTransform();

        int width = this.getWidth();
        int height = this.getHeight();
        g2d.translate(width / 2, height / 2);
        g2d.scale(1, -1);
        g2d.transform(viewpoint);

        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        paintGrid(g2d, width, height);
        root.paint(g2d, 0, 0, width, height);

        g2d.setTransform(transform);
    }

    private void paintGrid(Graphics2D g2d, int width, int height) {
        g2d.setPaint(Color.GRAY);
        g2d.fillOval(-3, -3, 6, 6);
        for (int i = (-width / 40 - 1) * 20; i < (width / 40 + 1) * 20; i += 20) {
            g2d.drawLine((int) i, -height, (int) i, height);
        }
        for (int i = (-height / 40 - 1) * 20; i < (height / 40 + 1) * 20; i += 20) {
            g2d.drawLine(-width, (int) i, width, (int) i);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Test frame");
        frame.getContentPane().add(new JCanvas());
        frame.setSize(800, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        frame.list(System.out);
    }
}
